home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
comm1
/
mscan.lha
/
MSCAN.ASM
< prev
next >
Wrap
Assembly Source File
|
1996-01-22
|
27KB
|
616 lines
;***** MSCAN V1.0 Source Code
;***** Quick message scan door for MAXsBBS V1.52+
;***** by Keith Bennett and Glen Martin 1996
;***** Last updated: 22-JAN-1996
;get some library offsets and constants
include "Assempro:Includes/exec.offsets"
include "Assempro:Includes/dos.offsets"
mode_old equ 1005
;set up some macros for library calls
callsys: macro $\1 ;macro for exec lib calls
jsr _LVO\1(a6)
endm
calldos: macro $\1 ;macro for dos lib calls
move.l doslibbase(pc),a6
jsr _LVO\1(a6)
move.w #4,a6
move.l (a6),a6
endm
bra begin ;vanity embedding
dc.b "MSCAN V1.0 for MAXsBBS "
dc.b "by Keith Bennett and Glen Martin 1996."
align
;***** START OF PROGRAM *****
begin: nop ;do nothing!
lea InitialSP(PC),a5 ;store the current stack pointer
move.l sp,(a5) ;in case we exit from a subroutine
move.w #4,a6 ;get the exec library base in a6
move.l (a6),a6
;***** READ SELECTED SECTION NUMBERS
subq.l #1,d0 ;did we get anything from the launch?
beq exit1 ;if not then lets get out of here
move.b #255,d7 ;set section number error flag
subq.l #1,d0 ;are there any parameters
beq getnoden ;nope, then skip
clr.l d7 ;reset section number error flag
move.l a0,a1 ;start of paramenters to a1
lea sections(PC),a2 ;point to section selection list
clr.l d3
paraloop: bsr readnum ;read next section number
tst.b d7 ;any error?
bmi getnoden ;yes
move.b #1,(a2,d1) ;set section as selected
backsep: move.b (a1)+,d2 ;read next character
beq getnoden ;end of parameters
cmp.b #" ",d2 ;is it a space?
beq getnoden ;yes, end of parameters
cmp.b #",",d2 ;is it a comma?
beq paraloop ;yes, read next section
move.b #255,d7 ;set error flag
cmp.b #"-",d2 ;is it a dash? (range)
bne getnoden ;no, (error)
clr.l d7 ;reset error flag
move.b d1,d3 ;remember previous number
bsr readnum ;read next section number
tst.b d7 ;any error?
bmi getnoden ;yes
sloop: cmp.b d1,d3 ;compare the values
bhs backsep ;end of range?
move.b #1,(a2,d3) ;set section as selected
addq #1,d3 ;increment section number
bra sloop ;loop until range is selected
;***** SET UP MESSAGE PORTS TO/FROM MAXS BBS
getnoden: add.l d0,a0 ;point a0 to node number
lea msgportn1+11(PC),a5 ;load the node number into the
move.b (a0),(a5) ;message control port name
lea msgportn2+9(PC),a5 ;and the reply port name
move.b (a0),(a5)
move.l #140,d0 ;get some ram for the message port
move.l #$10001,d1
callsys allocmem
lea msgport(PC),a5
move.l d0,(a5)
beq exit1 ;cant get it? then exit
sub.l a1,a1 ;find out who am I
callsys findtask
move.l (a5),a0
move.l d0,16(a0) ;get ourself a free signal
moveq #-1,d0
callsys allocsignal
move.l (a5),a1
move.b #4,8(a1) ;set up the message port
lea msgportn2(PC),a5
move.l a5,10(a1)
move.b d0,15(a1)
bmi exit2 ;if no free signals then exit
move.b #5,42(a1)
move.l a1,48(a1)
move.w #106,52(a1)
callsys addport ;add our message port
callsys forbid ;find max's control port
lea msgportn1(PC),a1
callsys findport
lea contport(PC),a5
move.l d0,(a5)
callsys permit
tst.l (a5)
beq exit3 ;if we cant find it then exit
;***** INITIALISE EVERYTHING
lea doslibname(PC),a1 ;open dos library
sub.l d0,d0
callsys openlibrary
lea doslibbase(PC),a5
move.l d0,(a5)
beq cleanup ;if we cant open it then exit
move.l bufflen(PC),d0 ;get some ram for the file buffer
move.l #$10000,d1
callsys allocmem
lea filebuff(PC),a5
lea txt07(PC),a0
move.l d0,(a5)
beq endit ;cant get it? then error and exit
moveq #8,d0 ;ask max for the BBS path
lea textbuff(PC),a3
bsr getstring
subq #1,a2 ;add on max's config filename
lea confname(PC),a0
loop02: move.b (a0)+,(a2)+
bne loop02
bsr openf ;open max's config file
lea txt03(PC),a0
tst.l d0 ;was the open successful?
beq endit ;no, show error and exit
move.l d0,d1 ;seek through max's config file to
move.l #144,d2 ;the message base path
moveq #-1,d3
calldos seek
move.l filehand(PC),d1 ;read the message base path
lea textbuff(PC),a0
move.l a0,d2
moveq #41,d3
calldos read
lea txt03(PC),a0
tst.l d0 ;did it read ok?
bmi endit ;no, show error and exit
move.l filehand(PC),d1 ;close max's config file
calldos close
lea filehand(PC),a0 ;clear filehandle
clr.l (a0)
lea textbuff(PC),a0 ;point to end of message base path
loop03: move.b (a0)+,d0
bne loop03
subq #1,a0
lea msgname(PC),a1 ;add on message.data filename
loop04: move.b (a1)+,(a0)+
bne loop04
bsr openf ;open message.data file
lea txt04(PC),a0
tst.l d0 ;did it open ok?
beq endit ;no, show error and exit
move.l d0,d1 ;seek though the message.data file to
move.l #470,d2 ;the message records
move.l #-1,d3
calldos seek
lea username(PC),a3 ;get user's username from max
moveq #1,d0
bsr getstring
lea accessl(PC),a3 ;get user's access level from max
moveq #1,d0
bsr getint
lea pagelen(PC),a3 ;get user's page length from max
moveq #9,d0
bsr getint
lea txt01(PC),a0 ;point to error text
cmp.b #255,d7 ;is d7 error staus? (255)
beq endit ;yes, display error and exit
;***** THE MAIN BIT
lea txt05(PC),a0 ;print heading
bsr print
lea txt11(PC),a0 ;underline the heading
bsr print
lea txt11(PC),a0
bsr print
lea txt02(PC),a0 ;and print a CR
bsr print
clr.l d6 ;clear message counter
moveq #6,d4 ;set initial number of lines displayed
mainloop: move.l filehand(PC),d1 ;read next block of message data
move.l filebuff(PC),d2
move.l bufflen(PC),d3
calldos read
lea txt04(PC),a0
move.l d0,d5 ;get number of bytes read
bmi endit ;error reading
beq eof ;end of file
move.l filebuff(PC),a4 ;point to start of message data
secdloop: btst #0,27(a4) ;deleted message?
bne next ;yes, next message
lea sections(PC),a0 ;point to selections
move.b 28(a4),d7 ;read section number from message
tst.b (a0,d7) ;it it selected?
beq next ;no, then next message
tst.b d7 ;private section?
bne display ;nope
move.l accessl(PC),d0 ;check access level
cmp.w #4999,d0 ;sysops see all private messages
bhi display
lea 70(a4),a0 ;is it to user?
bsr checkusrn
tst.l d0
bne display ;yes, display it
lea 29(a4),a0 ;is it from user?
bsr checkusrn
tst.l d0
beq next ;no, next message
display: move.l (a4),d0 ;read message number
bsr hxtoa ;convert to ASCII
move.l a1,a0 ;point to ASCII number
lea textbuff(PC),a1 ;point to text buffer
lea color1(PC),a2 ;point to ANSI color code
moveq #8,d0 ;set column width
bsr makeseg ;make first column
lea 183(a4),a0 ;point to from alias
move.b (a0),d0 ;is there an alias?
bne fromalias ;yes, skip
lea 29(a4),a0 ;no, point to to username
fromalias: lea color2(PC),a2 ;point to from ANSI color code
moveq #20,d0 ;set column width
bsr makeseg ;make the from column
move.b #0,(a1) ;terminate line
lea textbuff(PC),a0 ;print 1st half of line
bsr print ;(we need to print this line in 2 parts
lea textbuff(PC),a1 ; so we don't overrun the message port)
lea 224(a4),a0 ;point to to alias
move.b (a0),d0 ;is there a to alias?
bne toalias ;yes, skip
lea 70(a4),a0 ;no, point to to username
toalias: lea color3(PC),a2 ;point to ANSI color code
moveq #20,d0 ;set column width
bsr makeseg ;make the to column
lea 111(a4),a0 ;point to subject
lea color4(PC),a2 ;point to ANSI color code
moveq #31,d0 ;set column width
bsr makeseg ;make the last column
move.b #13,(a1)+ ;add CR to line
move.b #0,(a1) ;terminate line
lea textbuff(PC),a0 ;print 2nd half of line
bsr print
addq #1,d6 ;increment message counter
addq #1,d4 ;increment line count
cmp.l pagelen(PC),d4 ;end of page?
blo next ;no, next message
lea txt09(PC),a0 ;display hit return to continue...
bsr hotkey ;wait for user to press key
cmp.b #'S',d0 ;did user hit 'S' to stop?
beq eof ;yes, jump to end bit
lea txt08(PC),a0 ;backspace over message
bsr print
moveq #4,d4 ;reset line count
next: add.w #274,a4 ;point to next record
sub.l #274,d5 ;end of buffer?
bhi secdloop ;no, next record
bra mainloop ;yes, read next block
eof: lea txt02(PC),a0 ;print CR
bsr print
move.l d6,d0 ;convert message count to ascii
bsr hxtoa
move.l a1,a0 ;print message count
bsr print
lea txt10(PC),a0 ;point to message count text
endit: bsr print ;print message
lea txt06(PC),a0 ;display hit any key to end
bsr hotkey ;and wait for key
;***** CLEAN UP AND EXIT
cleanup: move.l filehand(PC),d1 ;get file handle
beq nof ;skip if file is not open
calldos close ;close file
nof: move.l filebuff(PC),a1 ;free file buffer ram
move.l a1,d0
beq nor ;but only if it's allocated
move.l bufflen(PC),d0
callsys freemem
nor: move.l doslibbase(PC),a1 ;get dos lib base
move.l a1,d0 ;test for zero
beq.s \skip ;is it open?
callsys closelibrary ;close if open
\skip: bsr getmsgport ;get message port
move.w #20,(a2) ;command #20 (exit door)
move.l contport(PC),a0 ;tell MAX's that i'm finished
callsys putmsg
\wait: move.l msgport(PC),a0 ;wait for reply
callsys waitport
move.l msgport(PC),a0 ;get reply
callsys getmsg
tst.l d0
beq \wait
exit3: move.l msgport(PC),a1 ;remove our message port
callsys remport
sub.l d0,d0 ;free our signal
move.l msgport(PC),a0
move.b 15(a0),d0
callsys freesignal
exit2: move.l msgport(PC),a1 ;free message port ram
move.l #140,d0
callsys freemem
exit1: move.l InitialSP(PC),sp ;recover the stack pointer
sub.l d0,d0
rts ;return
;***** READ A SECTION NUMBER (a1) to d1
readnum: clr.l d1 ;clear results
clr.l d2
move.b 1(a1),d1 ;read second character
cmp.b #'0',d1 ;is it a number?
blo digit1 ;no, only 1 digit
cmp.b #'9',d1 ;is it a number?
bhi digit1 ;no, only 1 digit
move.b (a1)+,d2 ;read first digit (10s)
cmp.b #'0',d2 ;is it a number?
blo numerr ;no, error
cmp.b #'9',d2 ;is it a number?
bhi numerr ;no error
sub.b #$30,d2 ;convert decimal to binary
mulu #10,d2 ;multiply by 10
digit1: move.b (a1)+,d1 ;read next digit
cmp.b #'0',d1 ;is it a number?
blo numerr ;no, error
cmp.b #'9',d1 ;is it a number?
bhi numerr ;no error
sub.b #$30,d1 ;convert decimal to binary
add.b d2,d1 ;add the 10s
rts ;return
numerr: move.b #255,d7 ;set error flag
clr.l d1 ;clear result
rts ;return
;***** MAKE A COLUMN OF THE LINE, (a0)=source, (a1)=dest, (a2)=ansi, d0=width
makeseg: move.b (a2)+,(a1)+ ;copy in ANSI color info
bne makeseg
subq #1,a1
subq #1,d0
\loop1: move.b (a0)+,d1 ;copy in info
beq \loop2 ;end of info
move.b d1,(a1)+
dbra d0,\loop1 ;loop up to width
tst.b (a1) ;are we at the end anyway?
beq \loop2 ;yes, no '+'
move.b #' ',-1(a1) ;info is bigger than width
move.b #'+',-2(a1) ;so put in a '+' indicator
rts ;return from subroutine
\loop2: move.b #" ",(a1)+ ;info is smaller that width
dbra d0,\loop2 ;so space fill the rest
rts ;return from subroutine
;***** CHECK USERNAME WITH (a0), d0=0 for no match
checkusrn: moveq #1,d0 ;set match flag
lea username(PC),a1 ;point to user's username
loopu: move.b (a0)+,d1 ;read character from message username
cmp.b #" ",d1 ;is it a space?
beq compskip1 ;yes, dont convert
and.b #$df,d1 ;convert to uppercase
compskip1: move.b (a1)+,d2 ;read character from username
cmp.b #" ",d2 ;is it a space?
beq compskip2 ;yes, dont convert
and.b #$df,d2 ;convert to uppercase
compskip2: cmp.b d1,d2 ;are they the same?
bne nomatch ;no, reset match flag and return
or.b d1,d2 ;both nulls? (end of username?)
bne loopu ;no, check next character
rts ;yes, return (match)
nomatch: clr.l d0 ;clear match flag
rts ;return from subroutine
;***** PRINT (a0)
print: bsr getmsgport ;get message port
move.w #1,(a2)+ ;command #1
clr.w (a2)+ ;no data
ploop: move.b (a0)+,(a2)+ ;put print text into message
bne ploop
bra putwmsg ;send the message then return
;***** DISPLAY (a0) AND HOTKEY TO d0
hotkey: bsr getmsgport ;get message port
move.w #8,(a2)+ ;command #8
clr.w (a2)+ ;no data
\loop: move.b (a0)+,(a2)+ ;copy print text into message
bne \loop
bsr putwmsg ;send message to max
move.b (a0),d0 ;read keypress
and.b #$df,d0 ;convert to uppercase
rts ;return from subroutine
;***** GET STRING INFO FROM MAX, d0=string type, result to (a3)
getstring: bsr getmsgport ;get message port
move.w #14,(a2)+ ;command #14
move.w d0,(a2) ;data=string type
bsr putwmsg ;send request to max
move.l a3,a2 ;store reply
\loop move.b (a0)+,(a2)+
bne \loop
rts ;return from subroutine
;***** GET INTEGER INFO FROM MAX, d0=int type, result(.l) to (a3)
getint: bsr getmsgport ;get message port
move.w #13,(a2)+ ;command #13
move.w d0,(a2) ;data=int type
bsr putwmsg ;send request to max
sub.l d0,d0 ;read result
move.w -(a0),d0
move.l d0,(a3) ;store result
rts ;return from subroutine
;***** GET MESSAGE PORT
getmsgport:move.l msgport(PC),a1 ;point to message port structure
move.l a1,a2
adda.w #34,a1 ;point a1 to message structure
adda.w #54,a2 ;point a2 to the message data
clr.l 2(a2) ;clear the data field
rts ;return
;***** SEND MESSAGE TO MAX's, WAIT FOR AND GET REPLY
putwmsg: move.l contport(PC),a0 ;point to message port structure
callsys putmsg ;send the message to MAX's
\wait: move.l msgport(PC),a0
callsys waitport ;wait for reply
move.l msgport(PC),a0
callsys getmsg ;get reply message
tst.l d0 ;did we get a reply
beq \wait ;no, keep waiting
move.l d0,a0 ;check for carrier loss
adda.w #24,a0
tst.w 80(a0)
bne cleanup ;carrier loss? if so then exit
rts ;return
;***** OPEN A FILE
openf: moveq #4,d5 ;number of times to attempt open
openloop: lea textbuff(PC),a0 ;point to file name
move.l a0,d1
move.l #mode_old,d2 ;open in read mode
calldos open ;open file
tst.l d0 ;did it open?
bne openok ;yes, store handle and return
calldos ioerr ;no, get error code
cmp.l #202,d0 ;is file in use?
bne openerror ;no, then it's a real error
move.l #64,d1 ;wait a few secs
calldos delay
dbra d5,openloop ;next attempt
openerror: clr.l d0 ;clear filehandle (error)
openok: lea filehand(PC),a0 ;store filehandle
move.l d0,(a0)
rts ;return
;CONVERT HEX (BINARY) d0 TO ASCII (a1)
hxtoa: tst.l d0 ;compliments Anthony Barrett's
bne skp04 ;door starter pack
lea cbuf3(PC),a1
move.b #'0',(a1)
clr.b 1(a1)
rts
skp04: lea cbuf3(PC),a1
move.l #$30303030,d1
move.l d1,(a1)+
move.l d1,(a1)+
move.w d1,(a1)
suba.w #28,a1
move.l d1,(a1)+
move.l d1,(a1)+
move.w #$3031,(a1)
nxbit: btst #0,d0
bne goada
retur: lsr.l #1,d0
beq endbit
lea cbuf2(PC),a1
lea cbuf1(PC),a2
move.l (a2)+,(a1)+
move.l (a2)+,(a1)+
move.w (a2),(a1)
addq.l #1,a1
addq.l #1,a2
bsr adasc
bra nxbit
endbit lea cbuf3(PC),a1
lop03: cmp.b #$30,(a1)+
beq.s lop03
subq.l #1,a1
rts
goada: lea cbuf1+9(PC),a1
lea cbuf3+9(PC),a2
bsr adasc
bra retur
adasc: moveq #9,d1
next1: move.b (a1),d2
sub.b #$30,d2
add.b d2,(a2)
check: cmp.b #$39,(a2)
bhi overf
subq.l #1,a2
retr2: subq.l #1,a1
dbf d1,next1
rts
overf: sub.b #10,(a2)
addq.b #1,-(a2)
movem.l a1/a2/d1,-(sp)
sub.l d1,d1
bsr check
movem.l (sp)+,d1/a2/a1
bra retr2
;***** DATA
;file and port names
msgportn1: dc.b "DoorControl#",0 ;message port name
msgportn2: dc.b "DoorReply#",0 ;message port name
doslibname:dc.b "dos.library",0 ;dos library name
msgname: dc.b "Message.data",0 ;message base file name
;error messages
txt01: dc.b 13,"Illegal message section selection format",13,0
txt03: dc.b 13,"Error accessing MAXsBBS config file",13,0
txt04: dc.b 13,"Error accessing Message base",13,0
txt07: dc.b 13,"Error allocating RAM",13,0
;text
txt02: dc.b $1b,"[0m",13,0
txt06: dc.b 13,"Hit any key to continue",0
txt08: dc.b 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
dc.b 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0
txt09: dc.b $1b,"[0;1;33mHit <RETURN> to continue (S - stop)... ",0
txt10: dc.b " messages were listed.",13,0
txt11: dc.b $1b,"[1;37m---------------------------------------",0
align.l
;storage
msgport: dc.l 0 ;message port
contport: dc.l 0 ;control port pointer
doslibbase:dc.l 0 ;dosbase store
InitialSP: dc.l 0 ;stack pointer store
filehand: dc.l 0 ;file handle
accessl: dc.l 0 ;access level
pagelen: dc.l 0 ;page length
filebuff: dc.l 0 ;file buffer pointer
username: blk.b 44,0 ;username
textbuff: blk.b 128,0 ;text buffer
cbuf1: blk.b 10,0 ;hex to acsii conversion ram
cbuf2: blk.b 10,0
cbuf3: blk.b 12,0
sections: blk.b 100,0 ;section selection list
align
;file buffer length
dc.b " File buffer length, must be a multiple of 274 (binary):"
bufflen: dc.l 274*100 ;read 100 messages at a time
;hex editable text
dc.b "You can hex edit these strings, all must be 0 terminated",13
dc.b "MAXs CONFIG FILE NAME:"
confname: dc.b "MAXsBBS.Config",0,0,0,0,0,0,0,0,0,0,0,0,0
dc.b "HEADING TEXT:"
txt05: dc.b $1b,"[H",$1b,"[2J",$1b,"[0;1;37mMSG No. FROM: "
dc.b "TO: SUBJECT:",13,0,0,0,0,0,0,0
dc.b "MSG No. COLOR:"
color1: dc.b $1b,"[0;32m",0,0,0,0,0
dc.b "TO COLOR:"
color2: dc.b $1b,"[0;37m",0,0,0,0,0
dc.b "FROM COLOR:"
color3: dc.b $1b,"[0;37m",0,0,0,0,0
dc.b "SUBJECT COLOR:"
color4: dc.b $1b,"[0;36m",0,0,0,0,0
end